{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Runnable interface \n",
    "可运行的接口\n",
    "\n",
    "To make it as easy as possible to create custom chains, we've implemented a \"Runnable\" protocol. Many LangChain components implement the Runnable protocol, including chat models, LLMs, output parsers, retrievers, prompt templates, and more. There are also several useful primitives for working with runnables, which you can read about in this section.\n",
    "\n",
    "为了尽可能轻松地创建自定义链，我们实现了“Runnable”协议。许多LangChain组件都实现了该协议 Runnable ，包括聊天模型、LLMs输出解析器、检索器、提示模板等。还有几个用于处理可运行对象的有用基元，您可以在本节中了解这些基元。\n",
    "\n",
    "> This is a standard interface, which makes it easy to define custom chains as well as invoke them in a standard way. The standard interface includes:<br>\n",
    "这是一个标准接口，可以很容易地定义自定义链并以标准方式调用它们。标准接口包括：\n",
    "\n",
    "* stream: stream back chunks of the response<br>\n",
    "stream ：流回响应块\n",
    "* invoke: call the chain on an input<br>\n",
    "invoke ：调用输入上的链\n",
    "* batch: call the chain on a list of inputs<br>\n",
    "batch ：调用输入列表上的链\n",
    "\n",
    "> These also have corresponding async methods that should be used with asyncio await syntax for concurrency:<br>\n",
    "这些方法还具有相应的异步方法，这些方法应与并发的 asyncio await 语法一起使用：\n",
    "\n",
    "* astream: stream back chunks of the response async<br>\n",
    "astream ：流回响应异步块\n",
    "* ainvoke: call the chain on an input async<br>\n",
    "ainvoke ：在输入异步上调用链\n",
    "* abatch: call the chain on a list of inputs async<br>\n",
    "abatch ：在输入列表中调用链 异步\n",
    "* astream_log: stream back intermediate steps as they happen, in addition to the final response<br>\n",
    "astream_log ：在中间步骤发生时流回中间步骤，以及最终响应\n",
    "* astream_events: beta stream events as they happen in the chain (introduced in langchain-core 0.1.14)<br>\n",
    "astream_events ：链中发生的 beta 流事件（在 0.1.14 中 langchain-core 引入）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> The input type and output type varies by component:<br>\n",
    "\n",
    " |\tComponent |\tInput  Type | Output Type |\t\n",
    " |\t:--- |\t:--- |\t:--- |\n",
    " |\tPrompt\t |\tDictionary |\t\tPromptValue |\t\n",
    " |\tChatModel\t |\tSingle string, list of chat messages or a PromptValue  |\t\tChatMessage |\t\n",
    " |\tLLM\t |\tSingle \tstring, list of chat messages or a PromptValue\t | String |\t\n",
    " |\tOutputParser |\tThe output of an LLM or ChatModel\t | Depends on the parser |\t\n",
    " |\tRetriever |\t\tSingle string\t | List of Documents |\t\n",
    " |\tTool\t |\tSingle string or dictionary, depending on the tool\t | Depends on the tool |\t\n",
    "\n",
    "> All runnables expose input and output schemas to inspect the inputs and outputs:<br>\n",
    "    `所有可运行项都公开输入和输出架构以检查输入和输出`\n",
    "\n",
    "* input_schema: an input Pydantic model auto-generated from the structure of the Runnable<br>\n",
    "    `从 Runnable 的结构自动生成的输入 Pydantic 模型`\n",
    "    \n",
    "* output_schema: an output Pydantic model auto-generated from the structure of the Runnable<br>\n",
    "    `从 Runnable 的结构自动生成的输出 Pydantic 模型`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI()\n",
    "prompt = ChatPromptTemplate.from_template(\"tell me a joke about {topic}\")\n",
    "chain = prompt | model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Input Schema\n",
    "A description of the inputs accepted by a Runnable. This is a Pydantic model dynamically generated from the structure of any Runnable. You can call .schema() on it to obtain a JSONSchema representation.<br>\n",
    "\n",
    "`Runnable 接受的输入的描述。这是一个 Pydantic 模型，由任何 Runnable 的结构动态生成。您可以调用 .schema() 它来获取 JSONSchema 表示形式。`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'title': 'PromptInput',\n",
       " 'type': 'object',\n",
       " 'properties': {'topic': {'title': 'Topic', 'type': 'string'}},\n",
       " 'required': ['topic']}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The input schema of the chain is the input schema of its first part, the prompt.\n",
    "chain.input_schema.schema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'title': 'PromptInput',\n",
       " 'type': 'object',\n",
       " 'properties': {'topic': {'title': 'Topic', 'type': 'string'}},\n",
       " 'required': ['topic']}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt.input_schema.schema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'title': 'ChatOpenAIInput',\n",
       " 'anyOf': [{'type': 'string'},\n",
       "  {'$ref': '#/definitions/StringPromptValue'},\n",
       "  {'$ref': '#/definitions/ChatPromptValueConcrete'},\n",
       "  {'type': 'array',\n",
       "   'items': {'anyOf': [{'$ref': '#/definitions/AIMessage'},\n",
       "     {'$ref': '#/definitions/HumanMessage'},\n",
       "     {'$ref': '#/definitions/ChatMessage'},\n",
       "     {'$ref': '#/definitions/SystemMessage'},\n",
       "     {'$ref': '#/definitions/FunctionMessage'},\n",
       "     {'$ref': '#/definitions/ToolMessage'}]}}],\n",
       " 'definitions': {'StringPromptValue': {'title': 'StringPromptValue',\n",
       "   'description': 'String prompt value.',\n",
       "   'type': 'object',\n",
       "   'properties': {'text': {'title': 'Text', 'type': 'string'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'StringPromptValue',\n",
       "     'enum': ['StringPromptValue'],\n",
       "     'type': 'string'}},\n",
       "   'required': ['text']},\n",
       "  'ToolCall': {'title': 'ToolCall',\n",
       "   'type': 'object',\n",
       "   'properties': {'name': {'title': 'Name', 'type': 'string'},\n",
       "    'args': {'title': 'Args', 'type': 'object'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'type': {'title': 'Type', 'enum': ['tool_call'], 'type': 'string'}},\n",
       "   'required': ['name', 'args', 'id']},\n",
       "  'InvalidToolCall': {'title': 'InvalidToolCall',\n",
       "   'type': 'object',\n",
       "   'properties': {'name': {'title': 'Name', 'type': 'string'},\n",
       "    'args': {'title': 'Args', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'error': {'title': 'Error', 'type': 'string'},\n",
       "    'type': {'title': 'Type',\n",
       "     'enum': ['invalid_tool_call'],\n",
       "     'type': 'string'}},\n",
       "   'required': ['name', 'args', 'id', 'error']},\n",
       "  'UsageMetadata': {'title': 'UsageMetadata',\n",
       "   'type': 'object',\n",
       "   'properties': {'input_tokens': {'title': 'Input Tokens', 'type': 'integer'},\n",
       "    'output_tokens': {'title': 'Output Tokens', 'type': 'integer'},\n",
       "    'total_tokens': {'title': 'Total Tokens', 'type': 'integer'}},\n",
       "   'required': ['input_tokens', 'output_tokens', 'total_tokens']},\n",
       "  'AIMessage': {'title': 'AIMessage',\n",
       "   'description': 'Message from an AI.\\n\\nAIMessage is returned from a chat model as a response to a prompt.\\n\\nThis message represents the output of the model and consists of both\\nthe raw output as returned by the model together standardized fields\\n(e.g., tool calls, usage metadata) added by the LangChain framework.',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'ai',\n",
       "     'enum': ['ai'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'example': {'title': 'Example', 'default': False, 'type': 'boolean'},\n",
       "    'tool_calls': {'title': 'Tool Calls',\n",
       "     'default': [],\n",
       "     'type': 'array',\n",
       "     'items': {'$ref': '#/definitions/ToolCall'}},\n",
       "    'invalid_tool_calls': {'title': 'Invalid Tool Calls',\n",
       "     'default': [],\n",
       "     'type': 'array',\n",
       "     'items': {'$ref': '#/definitions/InvalidToolCall'}},\n",
       "    'usage_metadata': {'$ref': '#/definitions/UsageMetadata'}},\n",
       "   'required': ['content']},\n",
       "  'HumanMessage': {'title': 'HumanMessage',\n",
       "   'description': 'Message from a human.\\n\\nHumanMessages are messages that are passed in from a human to the model.\\n\\nExample:\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import HumanMessage, SystemMessage\\n\\n        messages = [\\n            SystemMessage(\\n                content=\"You are a helpful assistant! Your name is Bob.\"\\n            ),\\n            HumanMessage(\\n                content=\"What is your name?\"\\n            )\\n        ]\\n\\n        # Instantiate a chat model and invoke it with the messages\\n        model = ...\\n        print(model.invoke(messages))',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'human',\n",
       "     'enum': ['human'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'example': {'title': 'Example', 'default': False, 'type': 'boolean'}},\n",
       "   'required': ['content']},\n",
       "  'ChatMessage': {'title': 'ChatMessage',\n",
       "   'description': 'Message that can be assigned an arbitrary speaker (i.e. role).',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'chat',\n",
       "     'enum': ['chat'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'role': {'title': 'Role', 'type': 'string'}},\n",
       "   'required': ['content', 'role']},\n",
       "  'SystemMessage': {'title': 'SystemMessage',\n",
       "   'description': 'Message for priming AI behavior.\\n\\nThe system message is usually passed in as the first of a sequence\\nof input messages.\\n\\nExample:\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import HumanMessage, SystemMessage\\n\\n        messages = [\\n            SystemMessage(\\n                content=\"You are a helpful assistant! Your name is Bob.\"\\n            ),\\n            HumanMessage(\\n                content=\"What is your name?\"\\n            )\\n        ]\\n\\n        # Define a chat model and invoke it with the messages\\n        print(model.invoke(messages))',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'system',\n",
       "     'enum': ['system'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'}},\n",
       "   'required': ['content']},\n",
       "  'FunctionMessage': {'title': 'FunctionMessage',\n",
       "   'description': 'Message for passing the result of executing a tool back to a model.\\n\\nFunctionMessage are an older version of the ToolMessage schema, and\\ndo not contain the tool_call_id field.\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'function',\n",
       "     'enum': ['function'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'}},\n",
       "   'required': ['content', 'name']},\n",
       "  'ToolMessage': {'title': 'ToolMessage',\n",
       "   'description': 'Message for passing the result of executing a tool back to a model.\\n\\nToolMessages contain the result of a tool invocation. Typically, the result\\nis encoded inside the `content` field.\\n\\nExample: A ToolMessage representing a result of 42 from a tool call with id\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import ToolMessage\\n\\n        ToolMessage(content=\\'42\\', tool_call_id=\\'call_Jja7J89XsjrOLA5r!MEOW!SL\\')\\n\\n\\nExample: A ToolMessage where only part of the tool output is sent to the model\\n    and the full output is passed in to artifact.\\n\\n    .. versionadded:: 0.2.17\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import ToolMessage\\n\\n        tool_output = {\\n            \"stdout\": \"From the graph we can see that the correlation between x and y is ...\",\\n            \"stderr\": None,\\n            \"artifacts\": {\"type\": \"image\", \"base64_data\": \"/9j/4gIcSU...\"},\\n        }\\n\\n        ToolMessage(\\n            content=tool_output[\"stdout\"],\\n            artifact=tool_output,\\n            tool_call_id=\\'call_Jja7J89XsjrOLA5r!MEOW!SL\\',\\n        )\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'tool',\n",
       "     'enum': ['tool'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'tool_call_id': {'title': 'Tool Call Id', 'type': 'string'},\n",
       "    'artifact': {'title': 'Artifact'}},\n",
       "   'required': ['content', 'tool_call_id']},\n",
       "  'ChatPromptValueConcrete': {'title': 'ChatPromptValueConcrete',\n",
       "   'description': 'Chat prompt value which explicitly lists out the message types it accepts.\\nFor use in external schemas.',\n",
       "   'type': 'object',\n",
       "   'properties': {'messages': {'title': 'Messages',\n",
       "     'type': 'array',\n",
       "     'items': {'anyOf': [{'$ref': '#/definitions/AIMessage'},\n",
       "       {'$ref': '#/definitions/HumanMessage'},\n",
       "       {'$ref': '#/definitions/ChatMessage'},\n",
       "       {'$ref': '#/definitions/SystemMessage'},\n",
       "       {'$ref': '#/definitions/FunctionMessage'},\n",
       "       {'$ref': '#/definitions/ToolMessage'}]}},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'ChatPromptValueConcrete',\n",
       "     'enum': ['ChatPromptValueConcrete'],\n",
       "     'type': 'string'}},\n",
       "   'required': ['messages']}}}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.input_schema.schema()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Output Schema\n",
    "A description of the outputs produced by a Runnable. This is a Pydantic model dynamically generated from the structure of any Runnable. You can call .schema() on it to obtain a JSONSchema representation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'title': 'ChatOpenAIOutput',\n",
       " 'anyOf': [{'$ref': '#/definitions/AIMessage'},\n",
       "  {'$ref': '#/definitions/HumanMessage'},\n",
       "  {'$ref': '#/definitions/ChatMessage'},\n",
       "  {'$ref': '#/definitions/SystemMessage'},\n",
       "  {'$ref': '#/definitions/FunctionMessage'},\n",
       "  {'$ref': '#/definitions/ToolMessage'}],\n",
       " 'definitions': {'ToolCall': {'title': 'ToolCall',\n",
       "   'type': 'object',\n",
       "   'properties': {'name': {'title': 'Name', 'type': 'string'},\n",
       "    'args': {'title': 'Args', 'type': 'object'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'type': {'title': 'Type', 'enum': ['tool_call'], 'type': 'string'}},\n",
       "   'required': ['name', 'args', 'id']},\n",
       "  'InvalidToolCall': {'title': 'InvalidToolCall',\n",
       "   'type': 'object',\n",
       "   'properties': {'name': {'title': 'Name', 'type': 'string'},\n",
       "    'args': {'title': 'Args', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'error': {'title': 'Error', 'type': 'string'},\n",
       "    'type': {'title': 'Type',\n",
       "     'enum': ['invalid_tool_call'],\n",
       "     'type': 'string'}},\n",
       "   'required': ['name', 'args', 'id', 'error']},\n",
       "  'UsageMetadata': {'title': 'UsageMetadata',\n",
       "   'type': 'object',\n",
       "   'properties': {'input_tokens': {'title': 'Input Tokens', 'type': 'integer'},\n",
       "    'output_tokens': {'title': 'Output Tokens', 'type': 'integer'},\n",
       "    'total_tokens': {'title': 'Total Tokens', 'type': 'integer'}},\n",
       "   'required': ['input_tokens', 'output_tokens', 'total_tokens']},\n",
       "  'AIMessage': {'title': 'AIMessage',\n",
       "   'description': 'Message from an AI.\\n\\nAIMessage is returned from a chat model as a response to a prompt.\\n\\nThis message represents the output of the model and consists of both\\nthe raw output as returned by the model together standardized fields\\n(e.g., tool calls, usage metadata) added by the LangChain framework.',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'ai',\n",
       "     'enum': ['ai'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'example': {'title': 'Example', 'default': False, 'type': 'boolean'},\n",
       "    'tool_calls': {'title': 'Tool Calls',\n",
       "     'default': [],\n",
       "     'type': 'array',\n",
       "     'items': {'$ref': '#/definitions/ToolCall'}},\n",
       "    'invalid_tool_calls': {'title': 'Invalid Tool Calls',\n",
       "     'default': [],\n",
       "     'type': 'array',\n",
       "     'items': {'$ref': '#/definitions/InvalidToolCall'}},\n",
       "    'usage_metadata': {'$ref': '#/definitions/UsageMetadata'}},\n",
       "   'required': ['content']},\n",
       "  'HumanMessage': {'title': 'HumanMessage',\n",
       "   'description': 'Message from a human.\\n\\nHumanMessages are messages that are passed in from a human to the model.\\n\\nExample:\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import HumanMessage, SystemMessage\\n\\n        messages = [\\n            SystemMessage(\\n                content=\"You are a helpful assistant! Your name is Bob.\"\\n            ),\\n            HumanMessage(\\n                content=\"What is your name?\"\\n            )\\n        ]\\n\\n        # Instantiate a chat model and invoke it with the messages\\n        model = ...\\n        print(model.invoke(messages))',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'human',\n",
       "     'enum': ['human'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'example': {'title': 'Example', 'default': False, 'type': 'boolean'}},\n",
       "   'required': ['content']},\n",
       "  'ChatMessage': {'title': 'ChatMessage',\n",
       "   'description': 'Message that can be assigned an arbitrary speaker (i.e. role).',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'chat',\n",
       "     'enum': ['chat'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'role': {'title': 'Role', 'type': 'string'}},\n",
       "   'required': ['content', 'role']},\n",
       "  'SystemMessage': {'title': 'SystemMessage',\n",
       "   'description': 'Message for priming AI behavior.\\n\\nThe system message is usually passed in as the first of a sequence\\nof input messages.\\n\\nExample:\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import HumanMessage, SystemMessage\\n\\n        messages = [\\n            SystemMessage(\\n                content=\"You are a helpful assistant! Your name is Bob.\"\\n            ),\\n            HumanMessage(\\n                content=\"What is your name?\"\\n            )\\n        ]\\n\\n        # Define a chat model and invoke it with the messages\\n        print(model.invoke(messages))',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'system',\n",
       "     'enum': ['system'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'}},\n",
       "   'required': ['content']},\n",
       "  'FunctionMessage': {'title': 'FunctionMessage',\n",
       "   'description': 'Message for passing the result of executing a tool back to a model.\\n\\nFunctionMessage are an older version of the ToolMessage schema, and\\ndo not contain the tool_call_id field.\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'function',\n",
       "     'enum': ['function'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'}},\n",
       "   'required': ['content', 'name']},\n",
       "  'ToolMessage': {'title': 'ToolMessage',\n",
       "   'description': 'Message for passing the result of executing a tool back to a model.\\n\\nToolMessages contain the result of a tool invocation. Typically, the result\\nis encoded inside the `content` field.\\n\\nExample: A ToolMessage representing a result of 42 from a tool call with id\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import ToolMessage\\n\\n        ToolMessage(content=\\'42\\', tool_call_id=\\'call_Jja7J89XsjrOLA5r!MEOW!SL\\')\\n\\n\\nExample: A ToolMessage where only part of the tool output is sent to the model\\n    and the full output is passed in to artifact.\\n\\n    .. versionadded:: 0.2.17\\n\\n    .. code-block:: python\\n\\n        from langchain_core.messages import ToolMessage\\n\\n        tool_output = {\\n            \"stdout\": \"From the graph we can see that the correlation between x and y is ...\",\\n            \"stderr\": None,\\n            \"artifacts\": {\"type\": \"image\", \"base64_data\": \"/9j/4gIcSU...\"},\\n        }\\n\\n        ToolMessage(\\n            content=tool_output[\"stdout\"],\\n            artifact=tool_output,\\n            tool_call_id=\\'call_Jja7J89XsjrOLA5r!MEOW!SL\\',\\n        )\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.',\n",
       "   'type': 'object',\n",
       "   'properties': {'content': {'title': 'Content',\n",
       "     'anyOf': [{'type': 'string'},\n",
       "      {'type': 'array',\n",
       "       'items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}]},\n",
       "    'additional_kwargs': {'title': 'Additional Kwargs', 'type': 'object'},\n",
       "    'response_metadata': {'title': 'Response Metadata', 'type': 'object'},\n",
       "    'type': {'title': 'Type',\n",
       "     'default': 'tool',\n",
       "     'enum': ['tool'],\n",
       "     'type': 'string'},\n",
       "    'name': {'title': 'Name', 'type': 'string'},\n",
       "    'id': {'title': 'Id', 'type': 'string'},\n",
       "    'tool_call_id': {'title': 'Tool Call Id', 'type': 'string'},\n",
       "    'artifact': {'title': 'Artifact'}},\n",
       "   'required': ['content', 'tool_call_id']}}}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The output schema of the chain is the output schema of its last part, in this case a ChatModel, which outputs a ChatMessage\n",
    "chain.output_schema.schema()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Stream"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Why did the bear break up with his girlfriend? Because he couldn't bear the relationship any longer!"
     ]
    }
   ],
   "source": [
    "for s in chain.stream({\"topic\": \"bears\"}):\n",
    "    print(s.content, end=\"\", flush=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Invoke"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content=\"Why don't bears wear socks?\\n\\nBecause they have bear feet!\", response_metadata={'token_usage': {'completion_tokens': 13, 'prompt_tokens': 13, 'total_tokens': 26}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-d9a1a4fc-b367-4969-9f70-88da67d84760-0', usage_metadata={'input_tokens': 13, 'output_tokens': 13, 'total_tokens': 26})"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({\"topic\": \"bears\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[AIMessage(content=\"Why did the bear break up with his girlfriend?\\nBecause he couldn't bear the relationship any longer!\", response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 13, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-64b03259-eb07-48b8-b058-e29378e4dd6a-0', usage_metadata={'input_tokens': 13, 'output_tokens': 20, 'total_tokens': 33}),\n",
       " AIMessage(content='Why was the cat sitting on the computer? Because it wanted to keep an eye on the mouse!', response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 13, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-51cc337f-3f58-41b2-b9fe-169d85b9e143-0', usage_metadata={'input_tokens': 13, 'output_tokens': 20, 'total_tokens': 33})]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.batch([{\"topic\": \"bears\"}, {\"topic\": \"cats\"}])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[AIMessage(content=\"Why did the bear break up with his girlfriend? \\n\\nBecause he couldn't bear the relationship any longer!\", response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 13, 'total_tokens': 34}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-b4f24556-b684-479b-833f-940b32f7dc93-0', usage_metadata={'input_tokens': 13, 'output_tokens': 21, 'total_tokens': 34}),\n",
       " AIMessage(content='Why was the cat sitting on the computer?\\n\\nBecause it wanted to keep an eye on the mouse!', response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 13, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-23c6e03b-5d71-49c9-b070-3bd9fbdf8e16-0', usage_metadata={'input_tokens': 13, 'output_tokens': 20, 'total_tokens': 33})]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.batch([{\"topic\": \"bears\"}, {\"topic\": \"cats\"}], config={\"max_concurrency\": 5})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Async Stream"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Why don't bears like fast food? Because they can't catch it!"
     ]
    }
   ],
   "source": [
    "async for s in chain.astream({\"topic\": \"bears\"}):\n",
    "    print(s.content, end=\"\", flush=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Async Invoke"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content=\"Why don't bears like fast food?\\n\\nBecause they can't catch it!\", response_metadata={'token_usage': {'completion_tokens': 15, 'prompt_tokens': 13, 'total_tokens': 28}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-1a503302-e416-49d9-b683-662d86c95ee7-0', usage_metadata={'input_tokens': 13, 'output_tokens': 15, 'total_tokens': 28})"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await chain.ainvoke({\"topic\": \"bears\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Async Batch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[AIMessage(content='Why did the bear bring a flashlight to the party? \\n\\nBecause he heard it was going to be a \"bear-y\" good time!', response_metadata={'token_usage': {'completion_tokens': 28, 'prompt_tokens': 13, 'total_tokens': 41}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-c0ed1af0-367f-4796-8d4a-05ce9ca666a3-0', usage_metadata={'input_tokens': 13, 'output_tokens': 28, 'total_tokens': 41})]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await chain.abatch([{\"topic\": \"bears\"}])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Parallelism"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.runnables import RunnableParallel\n",
    "\n",
    "chain1 = ChatPromptTemplate.from_template(\"tell me a joke about {topic}\") | model\n",
    "chain2 = (\n",
    "    ChatPromptTemplate.from_template(\"write a short (2 line) poem about {topic}\")\n",
    "    | model\n",
    ")\n",
    "combined = RunnableParallel(joke=chain1, poem=chain2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: total: 0 ns\n",
      "Wall time: 1.66 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "AIMessage(content='Why did the bear bring a flashlight to the party? \\n\\nBecause he heard it was going to be a \"beary\" good time!', response_metadata={'token_usage': {'completion_tokens': 28, 'prompt_tokens': 13, 'total_tokens': 41}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-1b14a0c0-0fa0-4888-a0cf-2607f81d8488-0', usage_metadata={'input_tokens': 13, 'output_tokens': 28, 'total_tokens': 41})"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "chain1.invoke({\"topic\": \"bears\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: total: 0 ns\n",
      "Wall time: 814 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "AIMessage(content='In the forest deep and wild,\\nBears roam freely, strong and mild.', response_metadata={'token_usage': {'completion_tokens': 16, 'prompt_tokens': 17, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-18835766-84aa-490a-9413-4a8d71241d96-0', usage_metadata={'input_tokens': 17, 'output_tokens': 16, 'total_tokens': 33})"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "chain2.invoke({\"topic\": \"bears\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: total: 0 ns\n",
      "Wall time: 1.39 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'joke': AIMessage(content=\"Why don't bears wear shoes?\\n\\nBecause they already have bear feet!\", response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 13, 'total_tokens': 27}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-f3e5cac7-69a2-479c-934d-627c6a662219-0', usage_metadata={'input_tokens': 13, 'output_tokens': 14, 'total_tokens': 27}),\n",
       " 'poem': AIMessage(content='In the forest they roam, powerful and grand\\nBears in their habitat, ruling the land', response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 17, 'total_tokens': 36}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-61895e98-7fc5-4c16-8b01-6b4a9d0a7639-0', usage_metadata={'input_tokens': 17, 'output_tokens': 19, 'total_tokens': 36})}"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "combined.invoke({\"topic\": \"bears\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Parallelism on batchesm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: total: 0 ns\n",
      "Wall time: 3.34 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[AIMessage(content='Why do bears have hairy coats?\\n\\nFur protection!', response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 13, 'total_tokens': 24}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-818ebae4-1a0b-4b9a-9836-9a3a3f89de7f-0', usage_metadata={'input_tokens': 13, 'output_tokens': 11, 'total_tokens': 24}),\n",
       " AIMessage(content='Why was the cat sitting on the computer?\\n\\nBecause it wanted to keep an eye on the mouse!', response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 13, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-f1ebb966-acc2-4c38-99e2-b8b91e95dea6-0', usage_metadata={'input_tokens': 13, 'output_tokens': 20, 'total_tokens': 33})]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "chain1.batch([{\"topic\": \"bears\"}, {\"topic\": \"cats\"}])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: total: 0 ns\n",
      "Wall time: 1.56 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[AIMessage(content='Bears roam the forest with strength and might,\\nTheir presence in the wild is a magnificent sight.', response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 17, 'total_tokens': 37}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-e1528bf6-a9fb-4d69-a457-c7a41b7b44ef-0', usage_metadata={'input_tokens': 17, 'output_tokens': 20, 'total_tokens': 37}),\n",
       " AIMessage(content='Whiskers soft, eyes bright,\\nPurring through the peaceful night.', response_metadata={'token_usage': {'completion_tokens': 15, 'prompt_tokens': 17, 'total_tokens': 32}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-b23687cb-b642-418b-bb71-7f456b19365b-0', usage_metadata={'input_tokens': 17, 'output_tokens': 15, 'total_tokens': 32})]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "chain2.batch([{\"topic\": \"bears\"}, {\"topic\": \"cats\"}])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: total: 0 ns\n",
      "Wall time: 1.45 s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[{'joke': AIMessage(content=\"Why did the bear break up with his girlfriend?\\n\\nBecause he couldn't bear the relationship any longer!\", response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 13, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-092469ab-ec36-469f-9028-d8fa88fb4441-0', usage_metadata={'input_tokens': 13, 'output_tokens': 20, 'total_tokens': 33}),\n",
       "  'poem': AIMessage(content='In the forest they roam, strong and free\\nBears, kings of the wilderness, wild and mighty', response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 17, 'total_tokens': 38}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-4ceff4b4-5711-4855-a1ae-ce894ca3c3f3-0', usage_metadata={'input_tokens': 17, 'output_tokens': 21, 'total_tokens': 38})},\n",
       " {'joke': AIMessage(content='Why was the cat sitting on the computer?\\n\\nBecause it wanted to keep an eye on the mouse!', response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 13, 'total_tokens': 33}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-f20405eb-654d-45ef-b785-ed24403295b5-0', usage_metadata={'input_tokens': 13, 'output_tokens': 20, 'total_tokens': 33}),\n",
       "  'poem': AIMessage(content='Whiskers soft, eyes bright\\nPurring companions in the night', response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 17, 'total_tokens': 31}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-e1c967d0-d5a7-4129-a304-a68563ac46ee-0', usage_metadata={'input_tokens': 17, 'output_tokens': 14, 'total_tokens': 31})}]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "combined.batch([{\"topic\": \"bears\"}, {\"topic\": \"cats\"}])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain0_1",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
